package top.huxy.boot.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import top.huxy.boot.annotation.Operation;
import top.huxy.boot.model.entity.Admin;
import top.huxy.boot.model.entity.OperationLog;
import top.huxy.boot.model.entity.User;
import top.huxy.boot.service.impl.OperationLogServiceImpl;
import top.huxy.boot.util.RequestUtils;
import top.huxy.boot.util.StringUtils;
import top.huxy.boot.util.obj.ThreadLocalAdmin;
import top.huxy.boot.util.obj.ThreadLocalRequestDetail;
import top.huxy.boot.util.obj.ThreadLocalUser;

/**
 * @Classname OperationAspect
 * @Description 日志记录操作
 * @Date 2021/9/24 17:20
 * @Created by huxy
 */
@Aspect
@Component
public class OperationAspect {

    @Autowired
    OperationLogServiceImpl operationLogService;

    //所有有这个注解的方法中的所有类
    @Pointcut("@annotation(operation)")
    public void operationPointcut(Operation operation) {
    }

    @Around("operationPointcut(operation)")
    public Object doAround(ProceedingJoinPoint joinPoint, Operation operation) throws Throwable {
        ThreadLocalRequestDetail current = ThreadLocalRequestDetail.current();
        User user = ThreadLocalUser.current();
        Admin admin = ThreadLocalAdmin.current();
        String operationName = operation.value();
        String methodDescription = StringUtils.getMethodDescription(((MethodSignature) joinPoint.getSignature()).getMethod());
        String requestId = null;
        Integer adminId = null;
        String userId = null;
        if (current != null) {
            requestId = RequestUtils.getRequestID(current.getRequest());
        }
        if (user != null) {
            userId = user.getId();
        }
        if (admin != null) {
            adminId = admin.getId();
        }
        Object result;
        boolean status = true;
        long time_start = System.currentTimeMillis();
        try {
            result = joinPoint.proceed();
        } catch (Throwable th) {
            status = false;
            throw th;
        } finally {
            long time_end = System.currentTimeMillis();
            int time = (int) (time_end - time_start);
            OperationLog operationLog = new OperationLog(
                    operationName,
                    methodDescription,
                    requestId,
                    time,
                    status,
                    adminId,
                    userId,
                    time_end);
            //保存到redis
            operationLogService.saveOperationLog2Redis(operationLog);
        }

        return result;
    }

}
